# -*- coding: utf-8 -*-

'''
	Soma Integral com Programacao funcional
'''

def f(x):
	return x

def integral_fun(f, a, b, x):
	
	'''
	por recursividade
	'''

	N = 40.0
	dx = (b - a) / N
	
	if x > b:
		return 0.0
	else:
		x += dx
		return f(x) * dx + integral_fun(f, a, b, x)

	pass


def integral_fun2(f, a, b):
	'''
	por reducao
	'''
	N = 1000 
	dx = (float(b) - float(a)) / float(N)

	lista_pontos = [a + k * dx for k in range(N)]

	return reduce(lambda x, y: x  + f(y) * dx, lista_pontos)

'''
Cálculo Interativo e Recursivo do Factorial
'''

def factorial_iterativo(n):
	'''
	Versao Interativa
	'''
	produto = 1
	for k in range(n, 0, -1):
		produto *= k
		pass
	return produto

def factorial(n):
	'''
	Versao Recursiva do calculo do factorial
	'''
	if n == 0:
		return 1
	else:
		return n * factorial(n -1)
	pass

def factorial_tail(n):
	'''
	Versao com tail recursivo
	'''
	def fact(i=n, acc = 1):
		if i == 0:
			return acc
		else:
			return fact(i -1, acc * i)
	return	fact()		

'''
Calculo dos Numeros de Fibonacci
'''

def fibinnaci_iterativo():
	n_k2 = 1
	n_k1 = 0
	n_k = 0
	k = 1
	while k <= n:
		n_k = n_k1 + n_k2
		n_k1,n_k2 = n_k2,n_k1
		k += 1
		pass

	return n_k

def fibinnaci_recursivo(n):
	if n == 0:
		return 0
	if n == 1:
		return 1
	else:
		return fibinnaci_recursivo(n -1) + fibinnaci_recursivo(n -2)
	pass 


def main():
	print integral_fun(f, 1, 8, 4)
	print integral_fun2(f, 1, 8)
	print factorial(4)
	print factorial_iterativo(4)
	print factorial_tail(4)
	print fibinnaci_recursivo(4)
	print fibinnaci_recursivo(5)
	
	'''
	Conjuntos e Eliminacao de valores redundantes
	Dicionarios e Codifiacao simplles
	'''
	
	# declaracao de uma lista arbitraria de numeros naturais
	lista = [1, 2, 8, 4, 5, 4, 4, 2, 8, 5, 2, 6]
	
	# formacao de conjuntos
	conj1 = set(lista)
	conj2 = set([1, 4, 5, 8])
	
	# interseccao de conjuntos
	conj3 = conj1.intersection(conj2)
	print conj3
	
	# lista com elementos nao redundantes
	lista1 = [x for x in conj1]
	print lista1
	
	#############################
	# dicionarios
	#############################
	
	# declaracao de dicionario
	d = {}
	
	# elementos de dicionario
	d['a'] = 'x' 
	d['e'] = 'y' 
	d['i'] = 'z' 
	d['o'] = 't' 
	d['u'] = 'w'
	
	frase = 'Cronus castrou o seu pai Urano' 
	
	# a frase 2 fica codificada
	frase2 = ''
	for x in frase:
		if x in set(['a','e','i','o','u']):
			frase2 += d[x]
		else:
			frase2 += x
		
		print frase2
		pass 
	
	
	# declaracao de uma funcao 
	f1 = lambda x: d[x] if x in d else x 
	
	# procedimento de codificacao funcional
	frase3 = reduce(lambda x,y: x + y, map(f, frase))
	
	# busca dos valores no diconario
	for chave, valor in d.iteritems():
		print chave, valor
	
	
	
	pass
	
main()
